package com.xiguaji.tiktok.v1.web.tiktok.controller;


import cn.hutool.core.date.DateUtil;
import com.xiguaji.tiktok.utils.CheckMobile;
import com.xiguaji.tiktok.utils.jwt.JwtUtil;
import com.xiguaji.tiktok.v1.product.dto.ReportTypeEnum;
import com.xiguaji.tiktok.v1.product.service.ProductService;
import com.xiguaji.tiktok.v1.tiktok.blogger.model.BloggerType;
import com.xiguaji.tiktok.v1.tiktok.blogger.service.BloggerService;
import com.xiguaji.tiktok.v1.tiktok.permission.repository.UserRoleRepository;
import com.xiguaji.tiktok.v1.tiktok.ranking.dto.SearchData;
import com.xiguaji.tiktok.v1.tiktok.ranking.service.RankingService;
import com.xiguaji.tiktok.v1.user.dto.UserReturnDto;
import com.xiguaji.tiktok.v1.user.model.User;
import com.xiguaji.tiktok.v1.user.service.UserService;
import com.xiguaji.tiktok.v1.user.validate.UserHandler;
import com.xiguaji.tiktok.v1.web.Tab;
import com.xiguaji.tiktok.v1.web.tiktok.dto.RankingFollowersResponse;
import com.xiguaji.tiktok.v1.web.tiktok.dto.RankingResponse;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.text.DecimalFormat;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

@Controller
@Slf4j
public class OfficialController {
    @Value("${server.domain}")
    String serverDomain;
    @Autowired
    BloggerService bloggerService;

    @Autowired
    RankingService rankingService;

    @Autowired
    RankingResponse.RankingResponseMapper rankingResponseMapper;

    @Autowired
    RankingFollowersResponse.RankingFollowersResponseMapper rankingFollowersResponseMapper;

    @Value("${jwt.head}")
    String authorized;

    @Autowired
    JwtUtil jwtUtil;

    @Autowired
    ProductService productService;

    @Autowired
    UserRoleRepository userRoleRepository;

    @Autowired
    UserHandler userHandler;

    /**
     * 用户服务
     */
    @Autowired
    UserService userService;

    DecimalFormat df = new DecimalFormat("######0.0");

    @RequestMapping("/")
    public ModelAndView official(ModelAndView modelAndView, HttpServletRequest request) {
        boolean isMobile = CheckMobile.check();
        /*if(isMobile){
            modelAndView.setViewName("redirect:/influencer/gdindex");
            return modelAndView;
        }*/

       String contextPath = request.getScheme() +"://" + request.getServerName()  + ":" +request.getServerPort() +request.getContextPath();
        System.out.println("in to official");
        LocalDateTime start = LocalDateTime.now();
        final int pageSize = 5;

        System.out.println(request.getRequestURL());
        System.out.println(request.getRequestURI());
        System.out.println(request.getContextPath());
        System.out.println(request.getPathInfo());
        System.out.println(request.getServletPath());
        System.out.println(request.getServerName());
        System.out.println(contextPath);

        List<BloggerType> typeList = new ArrayList<>();
        BloggerType type = new BloggerType();
        type.setName("All");
        type.setId(0);
        typeList.add(type);
        typeList.addAll(bloggerService.getTypeList().subList(0, 5));
        modelAndView.addObject("typeList", typeList);
        List<List<RankingResponse>> rankingList = new ArrayList<>();
        var dateCode = Integer.parseInt(DateUtil.format(LocalDateTime.now().minusDays(1), "yyyyMMdd"));
        val rankingDay = LocalDateTime.now().minusDays(1).format(DateTimeFormatter.ofPattern("MMMM dd", Locale.ENGLISH));
        modelAndView.addObject("rankingDay", rankingDay);
        LocalDateTime typeListTm = LocalDateTime.now();
        for (int i = 0; i < typeList.size(); i++) {
            SearchData searchData = new SearchData();
            searchData.setDate(dateCode);
            searchData.setRankingType(1);
            searchData.setBloggerTypeId((int) typeList.get(i).getId());
            val rankingResponses = rankingResponseMapper.mapper(rankingService.getRankingList(searchData, pageSize));

            rankingResponses.forEach(r -> {
                if((r.getAvatar().indexOf("sign-sg") > 0 && r.getAvatar().indexOf("sign-sg") < 30) || (r.getAvatar().indexOf("sign-va") > 0 && r.getAvatar().indexOf("sign-va") < 30)){
                    r.setAvatar(r.getAvatar().replace("sign-sg", "amd-va").replace("sign-va", "amd-va").replace("webp", "jpeg"));
                }
                r.setScore(getNumber(Double.parseDouble(r.getScore())));
                r.setFollower(getNumber(Long.parseLong(r.getFollower())));
                r.setLikesGrowth(getNumber(Long.parseLong(r.getLikesGrowth())));
                r.setReviewGrowth(getNumber(Long.parseLong(r.getReviewGrowth())));
                r.setShareGrowth(getNumber(Long.parseLong(r.getShareGrowth())));
            });
            rankingList.add(rankingResponses);
        }
        modelAndView.addObject("rankingList", rankingList);
        LocalDateTime rankingListTm = LocalDateTime.now();
        List<List<RankingFollowersResponse>> rankingFollowersList = new ArrayList<>();
        for (int i = 0; i < typeList.size(); i++) {
            SearchData searchData = new SearchData();
            searchData.setDate(dateCode);
            searchData.setRankingType(1);

            if (i == 0) {
                searchData.setBloggerTypeId(i);
            } else {
                searchData.setBloggerTypeId((int) typeList.get(i).getId());
            }
            val rankingFollowersResponses = rankingFollowersResponseMapper.mapper(rankingService.getRankingFollowersList(searchData, pageSize));
            rankingFollowersResponses.forEach(r->{
                if((r.getAvatar().indexOf("sign-sg") > 0 && r.getAvatar().indexOf("sign-sg") < 30) || (r.getAvatar().indexOf("sign-va") > 0 && r.getAvatar().indexOf("sign-va") < 30)){
                    r.setAvatar(r.getAvatar().replace("sign-sg", "amd-va").replace("sign-va", "amd-va").replace("webp", "jpeg"));
                }
                r.setFollower(getNumber(Long.parseLong(r.getFollower())));
                r.setFollowerGrowth(getNumber(Long.parseLong(r.getFollowerGrowth())));
            });

            rankingFollowersList.add(rankingFollowersResponses);
        }
        LocalDateTime rankingFollowersListTm = LocalDateTime.now();
        modelAndView.addObject("rankingFollowersList", rankingFollowersList);

        //用户信息
        UserReturnDto user = null;
        User u = userHandler.getUser();
        if(null != u){
            user = userService.getUser(u.getId());
        }

        modelAndView.addObject("login", user != null);
        modelAndView.addObject("user", user);
        modelAndView.addObject("tab", Tab.INDEX.getValue());
        modelAndView.addObject("contextPath",serverDomain);
        modelAndView.setViewName("index");
        modelAndView.addObject("helpUrl", this.serverDomain+"/help/home");
        modelAndView.addObject("isMobile", isMobile);

        //登录后导航栏显示的额外信息
        if(user != null){
            //用户信息
            modelAndView.addObject("userData",userService.getUser(user.getId()));
            //购买解锁报告的次数
            modelAndView.addObject("creditsBalance",productService.unlockedNumberByReportStarter(user.getId()));
            //会员剩余报告解锁次数
            modelAndView.addObject("dailyReportsBalance",productService.unlockedNumberByRole(user.getId(),user.getRoleId(), ReportTypeEnum.BLOGGER.getMsg()));
        }

        log.info("typeListTm={},rankingListTm={},rankingFollowersListTm={},all={}", timeBetweenMilli(start, typeListTm), timeBetweenMilli(typeListTm, rankingListTm), timeBetweenMilli(rankingListTm, rankingFollowersListTm), timeBetweenMilli(start, rankingFollowersListTm));
//        System.out.println("in to end official");
//        System.out.println("\"login\":"+ JsonUtil.parseJson(user != null));
//        System.out.println("\"rankingFollowersList\":"+ JsonUtil.parseJson(rankingFollowersList));
//        System.out.println("\"rankingList\":"+ JsonUtil.parseJson(rankingList));
//        System.out.println("\"rankingDay\":"+ JsonUtil.parseJson(rankingDay));
//        System.out.println("\"typeList\":"+ JsonUtil.parseJson(typeList));
//        System.out.println("\"contextPath\":"+ serverDomain);
        return modelAndView;
    }

    @RequestMapping("/policy")
    public ModelAndView policy(Integer type) {
        boolean active = false;
        if(type==null|| type == 0){
           active = true;
        }

        System.out.println("in to policy");
        ModelAndView modelAndView = new ModelAndView("policy");
        //用户信息
        UserReturnDto user = null;
        User u = userHandler.getUser();
        if(null != u){
            user = userService.getUser(u.getId());
        }
        modelAndView.addObject("login", user != null);
        modelAndView.addObject("user", user);
        modelAndView.addObject("active",active);
        modelAndView.addObject("isMobile", CheckMobile.check());
        modelAndView.addObject("contextPath",serverDomain);
        System.out.println("in to end policy");
        return modelAndView;
    }

    @RequestMapping("testpay")
    public ModelAndView payTest() {
        ModelAndView modelAndView = new ModelAndView("paypal");
        return modelAndView;
    }

    @RequestMapping("report")
    public ModelAndView report(){
        ModelAndView modelAndView = new ModelAndView("report/index");
        //用户信息
        UserReturnDto user = null;
        User u = userHandler.getUser();
        if(null != u){
            user = userService.getUser(u.getId());
        }
        modelAndView.addObject("isMobile", CheckMobile.check());
        modelAndView.addObject("unlocked",productService.getUnlockReport(user.getId()));
        modelAndView.addObject("expired",productService.getExpiredReport(user.getId()));
        modelAndView.addObject("creditsBalance",productService.unlockedNumberByReportStarter(user.getId()));
        modelAndView.addObject("dailyReportsBalance",productService.unlockedNumberByRole(user.getId(),user.getRoleId(),ReportTypeEnum.BLOGGER.getMsg()));
        modelAndView.addObject("myController",this);
        modelAndView.addObject("login", user != null);
        modelAndView.addObject("user", user);
        modelAndView.addObject("tab",Tab.REPORT.getValue());
        modelAndView.addObject("contextPath",serverDomain);
        return modelAndView;
    }

    @RequestMapping("order")
    public ModelAndView order(){
        //用户信息
        UserReturnDto user = null;
        User u = userHandler.getUser();
        if(null != u){
            user = userService.getUser(u.getId());
        }

        if(null == user){
            return new ModelAndView("redirect:/");
        }
        ModelAndView modelAndView = new ModelAndView("order/index");
        modelAndView.addObject("isMobile", CheckMobile.check());
        modelAndView.addObject("login", user != null);
        modelAndView.addObject("user", user);
        modelAndView.addObject("tab",Tab.ORDER.getValue());
        modelAndView.addObject("contextPath",serverDomain);
        return modelAndView;
    }


    private String getNumber(long num) {
        return getString(num, Math.abs(num), df.format(num));
    }
    private String getNumber(double num) {
        return getString(num, Math.abs(num), df.format(num));
    }

    private String getString(double num, double abs, String format) {
        return abs >= 1.0e+9
                ? df.format((num / 1.0e+9)) + "B"
                : abs >= 1.0e+6
                ? df.format((num / 1.0e+6)) + "M"
                : abs >= 1.0e+3
                ? df.format((num / 1.0e+3)) + "K"
                : format + "";
    }

    /**
     * 计算两个日期之间相差的秒数
     * 临时使用，较好的办法是放到工具类中
     * @param minDate 较小的时间
     * @param maxDate 较大的时间
     * @return 相差秒数
     */
    public static long timeBetweenSecond(LocalDateTime minDate, LocalDateTime maxDate) {
        Duration duration = Duration.between(minDate, maxDate);
        return duration.getSeconds();

    }

    /**
     * 计算两个日期之间相差的毫秒数
     * 临时使用，较好的办法是放到工具类中
     * @param minDate 较小的时间
     * @param maxDate 较大的时间
     * @return 相差毫秒数
     */
    public static long timeBetweenMilli(LocalDateTime minDate, LocalDateTime maxDate) {
        Duration duration = Duration.between(minDate, maxDate);
        return duration.toMillis();

    }

    public String dateTrans(long second){
        return LocalDateTime.ofInstant(Instant.ofEpochSecond(second), ZoneId.systemDefault()).format(DateTimeFormatter.ofPattern("MM-dd-yyyy HH:mm:ss"))+" UTC";
    }
}
